#include <stdio.h>
#include "Sign.h"

#define CSP_ID TEXT("{59651573-4967-4411-9B5B-239B0BD4383A}")
//#define CSP_ID NULL

void Sign()
{
	HCRYPTPROV hCryptProv;
	HCRYPTKEY  hKey;

	if ( CreateCryptoProvider( &hCryptProv ) == 0 )
	{
		if ( CreateCryptoKey( hCryptProv, &hKey, TEXT("PrivateKey.bin") ) == 0)
		{
			DWORD bufferSize;
			BYTE* buffer = LoadData(TEXT("macs.dat"), &bufferSize);

			if ( buffer )
			{
				SignBuffer(hCryptProv, buffer, bufferSize);
			}
		}
	}

	if ( hKey       ) CryptDestroyKey    ( hKey );
	if ( hCryptProv ) CryptReleaseContext(hCryptProv, 0);
}

void Verify()
{
	HCRYPTPROV hCryptProv;
	HCRYPTKEY  hKey;

	if ( CreateCryptoProvider( &hCryptProv ) == 0 )
	{
		if ( CreateCryptoKey( hCryptProv, &hKey, TEXT("PublicKey.bin") ) == 0)
		{
			DWORD bufferSize;
			BYTE* buffer = LoadData(TEXT("macs.dat"), &bufferSize);

			if ( buffer )
			{
				DWORD signSize;
				BYTE* sign = LoadData(TEXT("macs.sign2"), &signSize);
				if ( VerifyBuffer( hCryptProv, hKey,
					               buffer, bufferSize,    
								   sign  , signSize  ) == 0)
				{
					printf("ALl OK");
				}
			}
		}
	}

	if ( hKey       ) CryptDestroyKey    ( hKey );
	if ( hCryptProv ) CryptReleaseContext(hCryptProv, 0);

}

void GenKeys()
{
	HCRYPTPROV hCryptProv;

	if ( CreateCryptoProvider( &hCryptProv ) == 0 )
	{
		ExportKeys(hCryptProv);
	}
}

int ExportKeys( HCRYPTPROV hCryptProv )
{	
	HCRYPTKEY hKey = NULL;

	BYTE *publicKeyBlob;
	BYTE *privateKeyBlob;

	DWORD publicKeySize = NULL;
	DWORD privateKeySize = NULL;

	if ( CryptGenKey( hCryptProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKey) == TRUE ) 
	{
		// === Save private key =====================
		if ( CryptExportKey( hKey, 0, PRIVATEKEYBLOB, 0, NULL, &privateKeySize) == TRUE )
		{
			privateKeyBlob = (BYTE*)malloc(privateKeySize);

			if ( CryptExportKey( hKey, 0, PRIVATEKEYBLOB, 0, privateKeyBlob, &privateKeySize) == TRUE )
			{
				FILE* file = fopen( "PrivateKey.bin", "wb");
				fwrite( privateKeyBlob, 1, privateKeySize, file);
				fclose(file);
			}
		}

		// === Save public key =====================
		if ( CryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, NULL, &publicKeySize) == TRUE )
		{
			publicKeyBlob = (BYTE*)malloc(publicKeySize);

			if ( CryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, publicKeyBlob, &publicKeySize) == TRUE )
			{
				FILE* file = fopen( "PublicKey.bin", "wb");
				fwrite( publicKeyBlob, 1, publicKeySize, file);
				fclose(file);
			}
		}
	}

	if ( hKey ) CryptDestroyKey(hKey);

	free( publicKeyBlob );
	free( privateKeyBlob );

	return 0;
}

int SignBuffer( HCRYPTPROV hCryptProv, BYTE* buffer, DWORD bufferSize)
{
	HCRYPTHASH hHash;

	if ( CryptCreateHash( hCryptProv, CALG_SHA1, 0, 0, &hHash) == TRUE ) 
	{
		if ( CryptHashData( hHash, buffer, bufferSize, 0) == TRUE ) 
		{
			DWORD signSize;
			if ( CryptSignHash( hHash, AT_SIGNATURE, NULL, 0, NULL, &signSize) == TRUE ) 
			{
			   BYTE *sign = (BYTE*) malloc(signSize);

				if ( CryptSignHash( hHash, AT_SIGNATURE, NULL, 0, sign, &signSize) == TRUE ) 
				{
					FILE* file = fopen( "macs.sign2", "wb");
					fwrite( sign, 1, signSize, file);
					fclose(file);
				}
			}
		}
	}

	if ( hHash ) CryptDestroyHash(hHash);

	return 0;
}

